"""
用户相关接口
"""
import datetime
import re
from flask import Blueprint, request, current_app as app
from werkzeug.security import generate_password_hash, check_password_hash
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import Session

from model import model
from app.config import DevelopmentConfig
from src.utils import response_, verification

# 创建蓝图，第一个参数是蓝图的名字，第二个参数是所在模块
user_bp = Blueprint('user', __name__, url_prefix='/user')


@user_bp.route('/admin_login', methods=['POST'])
def login():
    data = request.get_json()
    try:
        if not data or not data.get('username') or not data.get('password'):
            return response_.error(message='Invalid request! Username and password required.', code=400)

        username: str = data['username']
        password: str = data['password']

        with Session(DevelopmentConfig.engine) as session:
            # 在 user_info 表中查询用户
            user = session.query(model.UserInfo).filter_by(username=username).first()

            # 验证用户是否存在
            if not user:
                app.logger.warning(f"登录尝试: 用户名 '{username}' 不存在")
                return response_.error(message='用户名或密码错误', code=401)

            # 验证密码
            if not check_password_hash(str(user.pwd), password):
                app.logger.warning(f"登录尝试: 用户 '{username}' 提供了错误的密码")
                return response_.error(message='用户名或密码错误', code=401)

            # 检查用户状态 (0:正常, 1:禁用)
            if user.status == 1:
                app.logger.warning(f"登录尝试: 用户 '{username}' 已被禁用")
                return response_.error(message='用户已被禁用，请联系管理员', code=403)

            user.last_login_at = datetime.datetime.now()

        # 生成JWT令牌
        token = verification.create_token(user.id, user.username, user.role)
        data = {
            'message': 'Login successful!',
            'token': token,
            'user': {
                'id': user.id,
                'username': user.username,
                'role': user.role
            }
        }
        return response_.success(data=data)
    except Exception as e:
        app.logger.error("Failed to fetch users", exc_info=True)
        return response_.error(message=str(e), code=500)
    finally:
        if session:
            session.close()


@user_bp.route('/logout', methods=['POST'])
@verification.token_required
def logout(current_user):
    """用户退出登录"""
    try:
        # 从请求头获取token
        auth_header = request.headers.get('Authorization')
        if not auth_header or 'Bearer ' not in auth_header:
            return response_.error(message="未提供认证token", code=401)

        token = auth_header.split(" ")[1]

        # 将token加入黑名单（使其失效）
        verification.revoke_token(token=token)

        # 返回成功响应
        return response_.success(
            message="退出登录成功",
            data={
                "username": current_user['username'],
                "logout_time": datetime.datetime.now().isoformat()
            },
            code=200
        )
    except IndexError:
        # app.logger.warning("无效的Authorization头格式")
        return response_.error(message="无效的认证格式，请使用 'Bearer <token>'", code=400)
    except Exception as e:
        app.logger.error("退出登录失败", exc_info=True)
        return response_.error(message="服务端错误: " + str(e), code=500)


@user_bp.route('/register', methods=['POST'])
def register():
    data = request.get_json()
    mobile = data['mobile']
    try:
        # 获取并验证请求数据
        if not data:
            return response_.error(message='请求体不能为空', code=400)

        # 检查必填字段
        required_fields = ['username', 'pwd', 'mobile']
        missing = [field for field in required_fields if field not in data]
        if missing:
            return response_.error(
                message=f'缺少必填字段: {", ".join(missing)}',
                code=400
            )

        # 验证手机号格式
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return response_.error(
                message='无效的手机号码格式',
                code=400
            )

        # 验证密码强度（至少8位，包含字母和数字）
        password = data['pwd']
        if len(password) < 8:
            return response_.error(
                message='密码至少需要8个字符',
                code=400
            )
        if not re.search(r'[A-Za-z]', password) or not re.search(r'\d', password):
            return response_.error(
                message='密码必须包含字母和数字',
                code=400
            )

        # 准备用户数据
        hashed_password = generate_password_hash(password)
        user_data = {
            'username': data['username'],
            'pwd': hashed_password,
            'mobile': mobile,
            'role': data.get('role', 'user'),  # 默认角色为user
            'status': 0  # 默认状态为正常
        }

        # 添加可选字段
        optional_fields = ['last_login_at']
        for field in optional_fields:
            if field in data:
                user_data[field] = data[field]

        # 创建新用户
        with Session(DevelopmentConfig.engine) as session:
            user = model.UserInfo(**user_data)
            session.add(user)
            session.commit()

            # 返回创建成功的用户信息（不包含密码）
            return response_.success(
                message='用户注册成功',
                data={
                    'id': user.id,
                    'username': user.username,
                    'mobile': user.mobile,
                    'role': user.role,
                    'status': user.status,
                    'create_time': user.create_time.isoformat() if user.create_time else None
                },
                code=201
            )

    except IntegrityError as e:
        # 处理唯一约束错误（用户名或手机号冲突）
        error_msg = str(e.orig).lower()
        if 'mobile' in error_msg:
            return response_.error(
                message=f'手机号 {mobile} 已被注册',
                code=409
            )
        elif 'username' in error_msg:
            return response_.error(
                message=f'用户名 {data["username"]} 已被使用',
                code=409
            )
        return response_.error(
            message='注册信息冲突',
            code=409
        )

    except Exception as e:
        app.logger.error(f"用户注册失败: {str(e)}", exc_info=True)
        return response_.error(
            message=f"注册失败: {str(e)}",
            code=500
        )